import { EditBox, find } from 'cc';
import { v3 } from 'cc';
import { game002 } from './../../Game002Manager';
import { _decorator, Component, Node, Button, Prefab, Label } from 'cc';
import { BasePanel } from '../../../../scripts/libs/ui/BasePanel';
import { BindButton } from '../../../../scripts/libs/rxjs/cc3/BindButton';
import { gm } from '../../../../scripts/managers/GameManager';
import { GameKey } from '../../../../scripts/managers/SubgameConfig';
import { instantiate } from 'cc';
import { Card } from './Card';
import { CardGroup } from './CardGroup';
import { EventTouch } from 'cc';
import { lm } from '../../../../ab_lobby/scripts/LobbyManager';
import { isValid } from 'cc';
import { Sprite } from 'cc';
import { Vec3 } from 'cc';
import { UITransform } from 'cc';
import { v2 } from 'cc';
import { geometry } from 'cc';
import { Rect } from 'cc';
import { ReactiveProperty } from '../../../../scripts/libs/rxjs/cc3/ReactiveProperty';
import { BindEditBox } from '../../../../scripts/libs/rxjs/cc3/BindEditBox';
import { subgame002 } from '../../Tools';
import { clipboardm } from '../../../../scripts/managers/ClipboardManager';
import { Player } from './Player';
const { ccclass, property } = _decorator;

const _v30 = v3();
const _v20 = v2();
const _aabb = new geometry.AABB();

export enum OutputType {
    ID,
    SYMBOL
}

@ccclass('MainPanel')
export class MainPanel extends BasePanel {

    @property(Prefab)
    playerPrefab: Prefab = null;

    @property(Prefab)
    cardPrefab: Prefab = null;

    @property(Prefab)
    cardGroupPrefab: Prefab = null;

    @property(Button)
    backButton: Button = null;

    @property(Button)
    resetButton: Button = null;

    @property(Button)
    outputTypeButton: Button = null;

    @property(Node)
    sourceCardsNode: Node = null;

    @property(Node)
    playersNode: Node = null;

    playerACardsNode: Node = null;
    playerBCardsNode: Node = null;
    playerCCardsNode: Node = null;
    playerDCardsNode: Node = null;

    @property(Node)
    cardsContainer: Node = null;

    @property(EditBox)
    editBox: EditBox = null;

    sourceCards: Card[] = [];

    jsonStr = ReactiveProperty.Create('');

    outputType = ReactiveProperty.Create(OutputType.ID);
    @property(Label)
    outputTypeLabel: Label = null;

    @property(Button)
    copyToClipboardButton: Button = null;

    @property(Button)
    loadButton: Button = null;

    willBind(): void {
        this.genPlayer();
        this.resetCards();
        globalThis.test1 = this;
    }

    genPlayer() {
        this.playersNode.destroyAllChildren();
        let playerANode = instantiate(this.playerPrefab);
        playerANode.setParent(this.playersNode);
        playerANode.getComponent(Player).playerName.value = 'A';
        this.playerACardsNode = find('Cards', playerANode);
        let playerBNode = instantiate(this.playerPrefab);
        playerBNode.setParent(this.playersNode);
        playerBNode.getComponent(Player).playerName.value = 'B';
        this.playerBCardsNode = find('Cards', playerBNode);
        let playerCNode = instantiate(this.playerPrefab);
        playerCNode.setParent(this.playersNode);
        playerCNode.getComponent(Player).playerName.value = 'C';
        this.playerCCardsNode = find('Cards', playerCNode);
        let playerDNode = instantiate(this.playerPrefab);
        playerDNode.setParent(this.playersNode);
        playerDNode.getComponent(Player).playerName.value = 'D';
        this.playerDCardsNode = find('Cards', playerDNode);
    }

    useObserves() {
        return [
            BindButton(this.backButton).subscribe(this.backbuttonClicked.bind(this)),
            BindButton(this.resetButton).subscribe(this.resetButtonClicked.bind(this)),
            BindButton(this.outputTypeButton).subscribe(this.outputTypeButtonClicked.bind(this)),
            BindButton(this.copyToClipboardButton).subscribe(this.copyToClipboardButtonClicked.bind(this)),
            BindButton(this.loadButton).subscribe(this.loadButtonClicked.bind(this)),
            game002.cardNodeTouchCommand.subscribe(this.cardNodeTouch.bind(this)),
            BindEditBox(this.editBox).subscribe(_ => { this.jsonStr.value = this.editBox.string }),
            this.jsonStr.subscribe(_ => {
                this.editBox.string = _;
            }),
            this.outputType.subscribe(_ => {
                if (_ == OutputType.ID) {
                    this.outputTypeLabel.string = 'ID模式';
                } else if (_ == OutputType.SYMBOL) {
                    this.outputTypeLabel.string = '符号模式';
                }
                this.refreshJson();
            })
        ];
    }

    backbuttonClicked() {
        this.log('backButtonClicked');
        gm.leaveGameCommand.execute(GameKey.subgame002);
    }

    resetButtonClicked() {
        this.log('resetButtonClicked');
        this.resetCards();
    }

    outputTypeButtonClicked() {
        this.log('outputTypeButtonClicked');
        this.outputType.value = (this.outputType.value + 1) % 2;
    }

    copyToClipboardButtonClicked() {
        this.log('copyToClipboardButtonClicked');
        clipboardm.CopyToClipboard(this.jsonStr.value);
    }

    loadButtonClicked() {
        this.log('loadButtonClicked');
        let obj = JSON.parse(this.jsonStr.value);
        this.loadJson(obj);
    }

    resetCards() {
        this.sourceCards = [];
        this.sourceCardsNode.destroyAllChildren();
        for (let i = 0; i < 52; i++) {
            let cardNode = instantiate(this.cardPrefab);
            let card = cardNode.getComponent(Card);
            card.cardId.value = i;
            card.cardIdOri = i;
            cardNode.parent = this.sourceCardsNode;
            this.sourceCards.push(card);
        }
        [this.playerACardsNode, this.playerBCardsNode, this.playerCCardsNode, this.playerDCardsNode].forEach(_ => {
            _.destroyAllChildren();
            this.genCardGroupNode(_);
        });
        this.refreshJson();
    }

    genCardGroupNode(parentNode: Node) {
        let cardGroupNode = instantiate(this.cardGroupPrefab);
        parentNode.addChild(cardGroupNode);
        let cardGroup = cardGroupNode.getComponent(CardGroup);
        cardGroup.clearCards();
        return cardGroup;
    }

    // _sub_swap_set = new Set<Subscription>();
    // _moving_idx = new Set<number>();
    _touchMoveCard: Node = null;
    _touchDiff = v3();
    _isClick = false;
    cardNodeTouch(param: { card: Card, eventTouch: EventTouch }) {
        let { card, eventTouch } = param;
        if (card.willDestroy) return;
        this.log('cardNodeTouch', card.cardId.value, eventTouch);
        if (eventTouch.type == 'touch-move' || eventTouch.type == 'touch-start') {
            lm.lobbySceneCanvas.touchLocationToWorldPosition(eventTouch.getLocation(), _v30);
            if (!isValid(this._touchMoveCard)) {
                if (card.cardId.value < 0) return;
                // frontNode0.active = false;
                this._touchMoveCard = instantiate(this.cardPrefab);
                let _card = this._touchMoveCard.getComponent(Card);
                _card.cardId.value = card.cardId.value;
                _card.enableTouch = false;
                this._touchMoveCard.setParent(this.cardsContainer);
                this._touchDiff.set(_v30).subtract(card.node.worldPosition);
                this._isClick = true;
                card.cardIdOri = card.cardId.value;
                card.cardId.value = -1;
            }
            this._touchMoveCard.setWorldPosition(_v30.subtract(this._touchDiff));

            // let cardGroup = this.getCardGroupByWorldPosition(this._touchMoveCard.worldPosition);
            // this.log('@test cardGroup', cardGroup);
            // let inSourceCard = this.inSourceCardsNodeByWorldPosition(this._touchMoveCard.worldPosition);
            // this.log('@@inSourceCard', inSourceCard);

        } else if (eventTouch.type == 'touch-end' || eventTouch.type == 'touch-cancel') {
            if (isValid(this._touchMoveCard)) {
                let cardGroup = this.getCardGroupByWorldPosition(this._touchMoveCard.worldPosition);
                let inSourceCard = this.inSourceCardsNodeByWorldPosition(this._touchMoveCard.worldPosition);
                let needClearOld = false;
                if (inSourceCard) {
                    let _card = this.sourceCardsNode.children[card.cardIdOri].getComponent(Card);
                    _card.cardId.value = _card.cardIdOri;
                    needClearOld = true;
                } else if (cardGroup != null) {
                    cardGroup.addCard(this._touchMoveCard.getComponent(Card).cardId.value);
                    needClearOld = true;
                }

                if (card.node.parent.name == 'CardGroup') { // 从CardGroup拖拽的
                    if (needClearOld) {
                        card.node.parent.getComponent(CardGroup).removeCard(card.cardIdOri, true);// 此处会导致touch-cancel迭代调用
                    } else {
                        card.cardId.value = card.cardIdOri;
                    }
                } else {
                    if (needClearOld) {
                    } else {
                        card.cardId.value = card.cardIdOri;
                    }
                }
                this._touchMoveCard.destroy();
                this._touchMoveCard = null;

                this.checkPlayerAndRefreshCardGroup();
                this.refreshJson();
            }
        }
    }

    inSourceCardsNodeByWorldPosition(worldPosition: Vec3): boolean {
        this.log('@test worldPosition', worldPosition);
        let t = this.sourceCardsNode.getComponent(UITransform);
        let rect = new Rect(this.sourceCardsNode.worldPosition.x - t.width / 2, this.sourceCardsNode.worldPosition.y - t.height / 2, t.width, t.height);
        return rect.contains(_v20.set(worldPosition.x, worldPosition.y));
    }

    getCardGroupByWorldPosition(worldPosition: Vec3): CardGroup {
        this.log('@test worldPosition', worldPosition);
        let playerCardNodes = [this.playerACardsNode, this.playerBCardsNode, this.playerCCardsNode, this.playerDCardsNode];
        for (let j = 0; j < playerCardNodes.length; j++) {
            let playerCardNode = playerCardNodes[j];
            let cardGroups = playerCardNode.getComponentsInChildren(CardGroup);
            for (let i = 0; i < cardGroups.length; i++) {
                let cardGroup = cardGroups[i];
                let t = cardGroup.getComponent(UITransform);
                let rect = new Rect(cardGroup.node.worldPosition.x - t.width / 2, cardGroup.node.worldPosition.y - t.height / 2, t.width, t.height);
                // rect.width = 52; // bug?
                // rect.height = 72;
                // this.log('@@aabb', j, i, rect.x, rect.y, rect.width, rect.height);
                if (rect.contains(_v20.set(worldPosition.x, worldPosition.y))) {
                    return cardGroup;
                }
            };
        }
        return null;
    }

    checkPlayerAndRefreshCardGroup() {
        let nodes = [this.playerACardsNode, this.playerBCardsNode, this.playerCCardsNode, this.playerDCardsNode];
        for (let i = 0; i < nodes.length; i++) {
            let node = nodes[i];

            let delCands: CardGroup[] = [];
            for (let i = 0; i < node.children.length; i++) {
                let cardGroup = node.children[i].getComponent(CardGroup);
                if (cardGroup.cards.length == 0) {
                    delCands.push(cardGroup);
                }
            }
            delCands.forEach(_ => {
                _.node.destroy();
            });

            this.genCardGroupNode(node);
        }
    }

    refreshJson() {
        // 上面牌库都显示出来
        // let nodes = [this.playerACardsNode, this.playerBCardsNode, this.playerCCardsNode, this.playerDCardsNode];
        let obj = [];
        for (let i = 0; i < this.playersNode.children.length; i++) {
            let player = this.playersNode.children[i].getComponent(Player);
            let node = player.cardsNode;
            let playerList = [];
            for (let i = 0; i < node.children.length; i++) {
                let cardGroup = node.children[i].getComponent(CardGroup);
                let cardsId = cardGroup.getCardsId();
                if (cardsId.length > 0) {
                    playerList.push(cardsId);
                }
            }
            obj.push(playerList);
            player.pattern.value = playerList;
        }
        if (this.outputType.value == OutputType.SYMBOL) {
            this.convertToSymbol(obj);
        }
        this.jsonStr.value = JSON.stringify(obj);
    }

    loadJson(obj, useSymbol = false) {
        this.outputType.value = useSymbol ? OutputType.SYMBOL : OutputType.ID;
        if (useSymbol) {
            this.convertToId(obj);
        }
        this.sourceCards.forEach(_ => {
            _.cardId.value = _.cardIdOri;
        });
        for (let i = 0; i < obj.length; i++) {
            let player = obj[i];
            let node = [this.playerACardsNode, this.playerBCardsNode, this.playerCCardsNode, this.playerDCardsNode][i];
            for (let j = 0; j < player.length; j++) {
                let group = player[j];
                let cardGroup = node.children[j]?.getComponent(CardGroup);
                if (cardGroup == null) {
                    cardGroup = this.genCardGroupNode(node);
                }
                cardGroup.clearCards();
                for (let k = 0; k < group.length; k++) {
                    let value: string = group[k];
                    // 检查内容是否是符号
                    // value可能是数字，也可能是例如'♥8'这样的字符串
                    // 区分数字和字符串
                    if (typeof value == 'string') {
                        this.loadJson(obj, true);
                        return;
                    }
                    cardGroup.addCard(group[k]);
                    // 用到的，牌库里面也需要删除
                    this.sourceCards[group[k]].cardId.value = -1;
                }
            }
        }
        this.checkPlayerAndRefreshCardGroup();
        this.refreshJson();
    }

    convertToSymbol(obj) {
        for (let i = 0; i < obj.length; i++) {
            let player = obj[i];
            for (let j = 0; j < player.length; j++) {
                let group = player[j];
                for (let k = 0; k < group.length; k++) {
                    group[k] = subgame002.tools.cardIdToSymbol(group[k]);
                }
            }
        }
    }

    convertToId(obj) {
        for (let i = 0; i < obj.length; i++) {
            let player = obj[i];
            for (let j = 0; j < player.length; j++) {
                let group = player[j];
                for (let k = 0; k < group.length; k++) {
                    group[k] = subgame002.tools.SymbolToCardId(group[k]);
                }
            }
        }
    }
}
